﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using CommonsLib.Utility;
using System.Web.Caching;
using System.Web;
using CommonsLib.Settings;

namespace MaxLeaf.Platform.DataContract
{
    /// <summary>
    /// 基类，不直接使用
    /// </summary>
    [Serializable]
    [DataContract]
    public class BaseDataModel
    {

       
        Dictionary<string, List<Cond>> _dictSubTableCond;
        Dictionary<string, object> _dictSubTableData;
        Dictionary<string, double> _dictSumData;
        private Dictionary<string, List<Cond>> dictCond
        {
            get
            {
                if (!string.IsNullOrEmpty(HttpRuntime.AppDomainAppVirtualPath))
                {
                    const string Cache_KEY="dictCond";
                    if (HttpRuntime.Cache[Cache_KEY] == null)
                    {
                        Dictionary<string, List<Cond>> dict = new Dictionary<string, List<Cond>>();
                        SetCache(Cache_KEY, dict,10);

                    }
                    return (Dictionary<string, List<Cond>>)HttpRuntime.Cache[Cache_KEY];
                }
                else
                {
                    if (_dictSubTableCond == null)
                    {
                        _dictSubTableCond = new Dictionary<string, List<Cond>>();
                    }
                }
                return _dictSubTableCond;
            }
        }

        public void ClearDictData()
        {
            lock (dictData)
            {
                dictData.Clear();
                //LogManager.Debug("clear dictData");
            }
        }
        private Dictionary<string, object> dictData
        {
            get
            {
                if (!string.IsNullOrEmpty(HttpRuntime.AppDomainAppVirtualPath))
                {
                    const string Cache_KEY = "dictData";
                    if (HttpRuntime.Cache[Cache_KEY] == null)
                    {
                        Dictionary<string, object> dict = new Dictionary<string, object>();
                        SetCache(Cache_KEY, dict,1);

                        //LogManager.Debug("Cache dictData");
                    }
                    return (Dictionary<string, object>)HttpRuntime.Cache[Cache_KEY];
                }
                else
                {
                    if (_dictSubTableData == null)
                    {
                        _dictSubTableData = new Dictionary<string, object>();
                        //LogManager.Debug("not Cache dictData");
                    }
                    return _dictSubTableData;
                }
            }
        }
        private Dictionary<string, double > dictSum
        {
            get
            {
                //if (!string.IsNullOrEmpty(HttpRuntime.AppDomainAppVirtualPath))
                //{
                //    if (HttpRuntime.Cache["dictSum"] == null)
                //    {
                //        Dictionary<string, double> dict = new Dictionary<string, double>();
                //        SetCache("dictSum", dict);

                //    }
                //    return (Dictionary<string, double>)HttpRuntime.Cache["dictSum"];
                //}
                //else
                //{
                     
                    if (_dictSumData == null)
                    {
                        _dictSumData = new Dictionary<string, double>();
                    }
                    return _dictSumData;
                //}
            }
        }


         private void SetCache(string strKeyName,object obj,int intExpireMinutes)     {
             //SetCacheDep();          
            //CacheDependency dep = new CacheDependency(null, new string[] { "CacheDep" },DateTime.Now);
            HttpRuntime.Cache.Insert(strKeyName
                , obj
                , null
                ,Cache.NoAbsoluteExpiration
                , intExpireMinutes.Equals(0) ? Cache.NoSlidingExpiration : new TimeSpan(0, intExpireMinutes, 0)  
                );     
        }

         //private void SetCacheDep()
         //{
         //    if (HttpRuntime.Cache["CacheDep"] == null)
         //    {
         //        HttpRuntime.Cache.Insert("CacheDep"
         //           , Guid.NewGuid().ToString()
         //           , null
         //           , Cache.NoAbsoluteExpiration
         //           , new TimeSpan(0, 1, 0)                    
         //           );
         //    }
         //}

       
        
        protected virtual T GetSubData<T>(object objOrgValue, string strDestPropName) where T : new()
        {
            List<Cond> lst = GetSubData_Cond<T>(objOrgValue, strDestPropName);

            return GetSubData<T>(lst);
            
        }

        private List<Cond> GetSubData_Cond<T>(object objOrgValue, string strDestPropName) where T : new()
        {
            string strKey = string.Format("{0}|{1}|{2}", typeof(T).Name, strDestPropName, objOrgValue);
            List<Cond> lst = null;
            lock (dictCond)
            {
                if (dictCond.ContainsKey(strKey))
                {
                    lst = dictCond[strKey];
                }

                if (lst == null)
                {
                    lst = new List<Cond> { new Cond { PropName = strDestPropName, Compare = CompareType.Equal, Value = objOrgValue } };
                    dictCond.Add(strKey, lst);

                }
            }
            return lst;
        }
        /// <summary>
        /// 获取关联表数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objOrgValue"></param>
        /// <param name="strDestPropName"></param>
        /// <returns></returns>
        protected virtual T GetSubData<T>(List<Cond> lstCond) where T : new()
        {



            string strSubTableKey = GetSubTableKey<T>(lstCond);
            lock (dictData)
            {
                if (dictData.ContainsKey(strSubTableKey))
                {
                    //LogManager.Debug(string.Format("GetSubData from Cache {0}", strSubTableKey));
                    return (T)dictData[strSubTableKey];
                }
            }
            //LogManager.Debug(string.Format("GetSubData from db {0}", strSubTableKey));


            T obj = new T();

            bool blnIsList = false;
            if (typeof(T).IsGenericType)
            {
                blnIsList = true;
            }

            List<object> lstSubTableModels = null;
            object submodel = System.Activator.CreateInstance(blnIsList ? typeof(T).GetGenericArguments()[0] : typeof(T));

            lstSubTableModels = SelectByCond(submodel
                , new List<AddInfo>(){
                                                new AddInfo{ Name= AddInfoType.Cond ,Value= lstCond
                                                }
                                        }
                ) ;

            if (blnIsList)
            {

                obj =(T)BaseFunctions.CreateGeneric(typeof(List<>), submodel.GetType());
                foreach (object subobj in lstSubTableModels)
                {
                    ((System.Collections.IList)obj).Add(subobj);
                }


            }
            else
            {
                if (lstSubTableModels == null || lstSubTableModels.Count == 0)
                {
                    obj = default(T);
                }
                else
                {
                    obj = (T)lstSubTableModels[0];
                }
            }


            SetSubData<T>(lstCond, obj);

            return obj;


        }

        private List<object>  SelectByCond(object submodel, List<AddInfo> list)
        {
            try
            {


                Type type = BLLProxyType;
                if (type != null)
                {
                    object oRpt = System.Activator.CreateInstance(type);

                    System.Reflection.MethodInfo mInfo = SelMethod;
                    object[] Param = { submodel, list };
                    if (mInfo != null)
                    {
                        SelectResult result = (SelectResult)mInfo.Invoke(oRpt, Param);
                        if (result != null)
                        {
                            return result.Data;
                        }

                    }
                }
                return null;
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return null;
            }
        }

        private string GetSubTableKey<T>(List<Cond> lstCond)
        {
            return string.Format("{0}|{1}", typeof(T).Name, GetKey_Cond(lstCond));
        }

        protected virtual void SetSubData<T>(object objOrgValue, string strDestPropName, T obj) where T : new()
        {
            List<Cond> lst = GetSubData_Cond<T>(objOrgValue, strDestPropName);
            SetSubData<T>(lst, obj);
        }
        /// <summary>
        /// 设置关联表数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objOrgValue"></param>
        /// <param name="obj"></param>
        protected virtual void SetSubData<T>( List<Cond> lstCond, T obj) where T : new()
        {
            lock (dictData)
            {
                string strSubTableKey = GetSubTableKey<T>(lstCond);

                if (dictData.ContainsKey(strSubTableKey))
                {
                    dictData[strSubTableKey] = obj;
                }
                else
                {
                    dictData.Add(strSubTableKey, obj);
                }
            }
            
        }


        private string GetSumKey<T>(string strDestPropName, List<Cond> lstCond,SumInfoType suminfoType)
        {
            return string.Format("{0}|{1}|{2}|{3}", typeof(T).Name, strDestPropName, suminfoType, GetKey_Cond(lstCond));
        }

        private string GetKey_Cond(List<Cond> lstCond)
        {
            string tmp = string.Empty;
            foreach (Cond cond in lstCond)
            {
                tmp += string.Format("|{0}|{1}|{2}",cond.PropName,cond.Compare,cond.Value );
            }

            return tmp;
        }
        /// <summary>
        /// 获取sum数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        protected virtual double GetSumData<T>(string strDestPropName,List<Cond> lstCond, SumInfoType suminfoType) where T : new()
        {
            string strSumKey = GetSumKey<T>(strDestPropName, lstCond, suminfoType);
            lock (dictSum)
            {
                if (dictSum.ContainsKey(strSumKey))
                {
                    return  dictSum[strSumKey];
                }
            }


            T obj = new T();

            bool blnIsList = false;
            if (typeof(T).IsGenericType)
            {
                blnIsList = true;
            }

            double dblValue = 0;
            object submodel = System.Activator.CreateInstance(blnIsList ? typeof(T).GetGenericArguments()[0] : typeof(T));

            dblValue = Sum(submodel
                , new List<AddInfo>(){
                                                new AddInfo{ Name= AddInfoType.Cond ,Value=lstCond}
                                                ,new AddInfo{ Name = AddInfoType.SumInfo , Value =new List<SumInfo>{ 
                                                    new SumInfo{ PropName=strDestPropName, SumType=  suminfoType }}}
                                        }
                );



            SetSumData<T>(strDestPropName, lstCond, suminfoType, dblValue);

            return dblValue;


        }

        /// <summary>
        /// 设置Sum数据
        /// </summary>
        protected virtual void SetSumData<T>(string strDestPropName, List<Cond> lstCond, SumInfoType suminfoType, double dblValue) where T : new()
        {
            lock (dictData)
            {
                string strSumKey = GetSumKey<T>(strDestPropName, lstCond, suminfoType);

                if (dictSum.ContainsKey(strSumKey))
                {
                    dictSum[strSumKey] = dblValue;
                }
                else
                {
                    dictSum.Add(strSumKey, dblValue);
                }
            }

        }


        private double  Sum(object submodel, List<AddInfo> list)
        {
            try
            {


                Type type = BLLProxyType;
                if (type != null)
                {
                    object oRpt = System.Activator.CreateInstance(type);
                    
                    System.Reflection.MethodInfo mInfo =SumMethod;
                    object[] Param = { submodel, list };
                    if (mInfo != null)
                    {
                        SumResult result = (SumResult)mInfo.Invoke(oRpt, Param);
                        if (result != null)
                        {
                            return result.Data[0];
                        }

                    }
                }
                return 0;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return 0;
            }
        }

        Type _BLLProxyType = null;
        private Type BLLProxyType
        {
            get
            {
                if (_BLLProxyType == null)
                {
                    _BLLProxyType = Type.GetType(
                        "MaxLeaf.Platform.BLLProxy.MtnBLLProxy,MaxLeaf.Platform.BLLProxy"
                        , true, true);

                }
                return _BLLProxyType;
            }
        }
        System.Reflection.MethodInfo _SelMethod=null;
        private System.Reflection.MethodInfo SelMethod
        {
            get
            {

                if (_SelMethod == null)
                {
                    _SelMethod = BLLProxyType.GetMethod("SelectByCond");
                }
                return _SelMethod;
            }
        }
        System.Reflection.MethodInfo _SumMethod = null;
        private System.Reflection.MethodInfo SumMethod
        {
            get
            {

                if (_SumMethod == null)
                {
                    _SumMethod = BLLProxyType.GetMethod("Sum");
                }
                return _SumMethod;
            }
        }
    }
}
